﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using vudu.Logica.Clases;
using vudu.EnlaceDatos.SqlServer;
using System.Net.Mail;
using System.Net;

namespace vudu.Logica.Clases
{
    public class Estudiante
    {
        #region Private Member Variables

        private int _idEst;
        private int _cedula;
        private string _noExpediente;
        private string _nombre;
        private string _apellido;
        private string _sexo;
        private string _telefono;
        private DateTime _fechaNacimiento;
        private string _carrera;
        private string _semestre;
        private string _correo;

        private SqlServerEstudiante _mibd;


        private List<Materia> _listaMateriasAprobadas;
        private List<HorarioPreMatricula> _listaHorarioPreMatricula;

        private List<Materia> _misMateriasSeleccionadasPreMatricula;//GRUPO 2
        private List<SeccionMateria> _misSeccionesSeleccionadasPreMatricula; //GRUPO 2

        private HorarioPreMatricula _preMatriculaModificable; //GRUPO 2

        private int _pageCounter; //GRUPO 2
        private bool _havePractice; //GRUPO 2

        private HorarioDeClase _horarioChoque1; //GRUPO 2
        private HorarioDeClase _horarioChoque2; //GRUPO 2

        private int _secuenceCounter; //GRUPO 2

        #endregion

        #region Constructors

        public Estudiante()
        {
            _carrera = _semestre = " ";
            _mibd = new SqlServerEstudiante();
            //miPensum = new Pensum();
            _preMatriculaModificable = new HorarioPreMatricula(); //GRUPO 2
            _pageCounter = 0; //GRUPO 2
            _secuenceCounter = 0; //GRUPO 2
        }

        #endregion

        #region Public Properties

        public int IdEst
        {
            get { return _idEst; }
            set { _idEst = value; }
        }

        public string Carrera
        {
            get { return _carrera; }
            set { _carrera = value; }
        }
        
        public string Semestre
        {
            get { return _semestre; }
            set { _semestre = value; }
        }

        ///<summary>
        /// public List<Profesor> ConsultarProfesor(int tipoConsulta)
        /// {
        ///    return (new List<Profesor>());
        /// }
        /// </summary>

        public int Cedula
        {
            get { return _cedula; }
            set { _cedula = value; }
        }

        public String Expediente
        {
            get { return _noExpediente; }
            set { _noExpediente = value; }
        }

        public string Nombre
        {
            get { return _nombre; }
            set { _nombre = value; }
        }

        public string Apellido
        {
            get { return _apellido; }
            set { _apellido = value; }
        }

        public string Sexo
        {
            get { return _sexo; }
            set { _sexo = value; }
        }

        public string Telefono
        {
            get { return _telefono; }
            set { _telefono = value; }
        }

        public DateTime FechaNacimiento
        {
            get { return _fechaNacimiento; }
            set { _fechaNacimiento = value; }
        }

        public string Correo
        {
            get { return _correo; }
            set { _correo = value; }
        }

        public List<HorarioPreMatricula> ListaHorarioPreMatricula
        {
            get { return _listaHorarioPreMatricula; }
            set { _listaHorarioPreMatricula = value; }
        }

        public List<Materia> MisMateriasSeleccionadasPreMatricula
        {
            get { return _misMateriasSeleccionadasPreMatricula; }
            set { _misMateriasSeleccionadasPreMatricula = value; }
        }

        public List<SeccionMateria> MisSeccionesSeleccionadasPreMatricula
        {
            get { return _misSeccionesSeleccionadasPreMatricula; }
            set { _misSeccionesSeleccionadasPreMatricula = value; }
        }
		
        public List<Materia> ListaMateriasAprobadas
        {
            get { return _listaMateriasAprobadas; }
            set { _listaMateriasAprobadas = value; }
        }

        public HorarioPreMatricula PreMatriculaModificable
        {
            get { return _preMatriculaModificable; }
            set { _preMatriculaModificable = value; }
        }

        public int PageCounter
        {
            get { return _pageCounter; }
            set { _pageCounter = value; }
        }

        public bool HavePractice
        {
            get { return _havePractice; }
            set { _havePractice = value; }
        }

        public HorarioDeClase HorarioChoque1
        {
            get { return _horarioChoque1; }
            set { _horarioChoque1 = value; }
        }

        public HorarioDeClase HorarioChoque2
        {
            get { return _horarioChoque2; }
            set { _horarioChoque2 = value; }
        }

        public int SecuenceCounter
        {
            get { return _secuenceCounter; }
            set { _secuenceCounter = value; }
        }

        #endregion

        #region Public Methods

        public bool ConsultarEstudiante(int cedula)
        {
            return false;
        }

        public List<Estudiante> ConsultarTodoEstudiante()
        {
            List<Estudiante> est = new List<Estudiante>();
            est = _mibd.ConsultarTodosLosEstudiante();
            return est;
        }

        public int InsertarEstudiante(Estudiante estudiante)
        {
            int a = 0;
            a = _mibd.InsertarEstudiante(estudiante);
            return a;
        }

        public int InsertarEstudianteEscuela(int idestudiante, int idescuela, DateTime fecha)
        {
            int a = 0;
            a = _mibd.InsertarEstudianteEscuela(idestudiante, idescuela, fecha);
            return a;
        }

        public Estudiante ConsultarEstudianteCedula(int cedula)
        {
            Estudiante Est = new Estudiante();
            Est = _mibd.ConsultarEstudianteCedula(cedula);
            return Est;
        }

        public Estudiante ConsultarEstudianteExpe(string expediente)
        {
            Estudiante Est = new Estudiante();
            Est = _mibd.ConsultarEstudianteExpe(expediente);
            return Est;
        }

        public int ConsultarEstudianteExistente(int cedula)
        {
            int Est;
            Est = _mibd.ConsultarEstudianteExistente(cedula);
            return Est;
        }

        #region GRUPO 2 - Metodos para Gestion de Horarios PreMatricula

            public void InsertarHorario(HorarioPreMatricula miHorarioPreMatricula)
            {
                
                /*
                 * En este procedimiento se recibe el horario que el estudiante desea agregar y se instancia una clase
                 * de tipo SqlServerHoraioPreMatricula y se le manda el id del estudiante actual junto con el horario.
                 * Se agrega el horario a la lista actual de horarios del estudiante.
                 */

                try
                {

                    SqlServerHorarioPreMatricula sqlServer = new SqlServerHorarioPreMatricula();
                    if (sqlServer.AgregarPreMatricula(this.IdEst, miHorarioPreMatricula) == true)
                        this.ListaHorarioPreMatricula.Add(miHorarioPreMatricula);
                }
                catch (Exception)
                { }
            }

            public void EliminarHorario(int idPreMatricula)
            {
                
                /*
                 * Este procedimiento se encarga de eliminar el Horario cuyo id sea el que se recibio por parametro,
                 * instancia un objeto de tipo SqlServerHorarioPreMatricula para ejecutar la funcion que elimine
                 * en base de datos el horario.
                 */

                try
                {
                    this.ListaHorarioPreMatricula.RemoveAll(
                        delegate(HorarioPreMatricula miHorarioPreMatricula)
                        {
                            return miHorarioPreMatricula.Codigo == idPreMatricula;
                        });
                    SqlServerHorarioPreMatricula sqlEliminarHorario = new SqlServerHorarioPreMatricula();
                    sqlEliminarHorario.EliminarPreMatricula(idPreMatricula);
                }
                catch (Exception)
                { }
            }

            public List<Materia> GenerarMateriasPreCandidatas()
            {
                
                /*
                 * Esta funcion se encarga de pedir a la clase de SqlServerHorarioPreMatricula la lista de las Prelaciones
                 * que existen para el periodo academico vigente y la lista de materias que ha aprobado el estudiante, la
                 * lista de prelaciones se irá filtrando por medio de la implementacion de 3 filtros actualmente creados,
                 * el primer filtro se encarga de eliminar las materias aprobadas de la lista de prelaciones, hay que acotar
                 * que esta lista de prelaciones son las materias del semestre, es decir, que una vez pasado por el primer
                 * filtro, quedan las materias que el estudiante aun no ha visto. El resultado de este filtro se guarda en 
                 * la lista llamada "listaCandidatas" de tipo Prelacion, en el segundo filtro lo que se hace es que, en cada
                 * prelacion, como tiene su lista de materias que prelan la materia base, se van eliminando de estas listas
                 * las materias que ya aprobo el estudiante dejandome la lista de candidatas solo con las materias que aun no
                 * ha visto y la listas de materias prelantes de cada una de estas materias bases sin las materias pasadas, 
                 * el Tercer y ultimo filtro se encarga de agregar a la lista de retorno las materias que posean la lista de
                 * materias prelantes vacias para ser retornada.
                 */

                try
                {
                    List<Materia> retorno = new List<Materia>();
                    List<Prelacion> listaCandidatas = new List<Prelacion>();
                    List<Materia> materiasAprobadas = new List<Materia>();
                    List<Prelacion> materias = new List<Prelacion>();
                    SqlServerHorarioPreMatricula sql = new SqlServerHorarioPreMatricula();
                    materiasAprobadas = sql.MisMateriasAprobadas(this._idEst);
                    materias = sql.MateriasDisponibles(this._carrera);

                    // Primer Filtro: Elimina de la lista de Prelaciones las materias aprobadas
                    foreach (Prelacion materia in materias)
                    {
                        bool bandera = false;
                        foreach (Materia miMateria in materiasAprobadas)
                        {
                            if (miMateria.Codigo == materia.MiMateriaPensum.Codigo)
                            {
                                bandera = true;
                            }
                        }
                        if (bandera == false)
                        {
                            listaCandidatas.Add(materia);
                        }
                    }
                    // Segundo Filtro: Filtrar SubLista de Materias que Prelan
                    foreach (Materia materiaPasada in materiasAprobadas)
                    {
                        foreach (Prelacion prelacion in listaCandidatas)
                        {
                            if (prelacion.Prelaciones != null)
                                prelacion.Prelaciones.Remove(materiaPasada);
                        }
                    }
                    // Tercer Filtro: Mandar las prelaciones que tengan la lista de materias vacia
                    foreach (Prelacion prelacion in listaCandidatas)
                    {
                        if ((prelacion.Prelaciones == null) || (prelacion.Prelaciones.Count == 0))
                        {
                            retorno.Add(prelacion.MiMateriaPensum);
                        }
                    }
                    return retorno;
                }
                
                catch (Exception)
                {
                    return null;
                }
            }

            public List<Materia> ConsultarMateriasAprobadas()
            {
                
                /*
                 * Esta funcion se encarga de retornar la lista de materias que lleva aprobada el estudiante actual.
                 */

                try
                {
                    List<Materia> miLista = new List<Materia>();
                    SqlServerHorarioPreMatricula sqlServer = new SqlServerHorarioPreMatricula();
                    miLista = sqlServer.MisMateriasAprobadas(this._idEst);
                    return miLista;
                }
                catch (Exception)
                {
                    return null;
                }

            }

            public List<Materia> GenerarMateriasObligatorias(List<Materia> misMateriasCandidatas)
            {
                //Regresa la lista de materias obligatorias, es decir estas materias ajuro van
                //dentro de la prematricula

                try
                {

                    int menorSemestre;
                    List<Prelacion> misPrelacionesObligatorias = new List<Prelacion>();
                    List<Materia> misMateriasObligatorias = new List<Materia>();
                    SqlServerHorarioPreMatricula sqlPrelaciones = new SqlServerHorarioPreMatricula();
                    List<Prelacion> misPrelaciones = new List<Prelacion>();
                    misPrelaciones = sqlPrelaciones.MateriasDisponibles(this.Carrera);
                    //Obtencion de las prelaciones precandidatas, comparando con las materias precandidatas
                    foreach (Prelacion miMateriaPrelada in misPrelaciones)
                    {
                        foreach (Materia miMateriaCandidata in misMateriasCandidatas)
                        {
                            if (miMateriaPrelada.MiMateriaPensum.Codigo == miMateriaCandidata.Codigo)
                            {
                                misPrelacionesObligatorias.Add(miMateriaPrelada);
                            }
                        }
                    }
                    //Se oredena ascendente por semestre para obtener las materias obligatorias
                    misPrelacionesObligatorias.Sort(delegate(Prelacion miPrelacion1, Prelacion miPrelacion2)
                    {
                        return miPrelacion1.SemestreMateriaPensum.CompareTo(miPrelacion2.SemestreMateriaPensum);
                    });
                    menorSemestre = misPrelacionesObligatorias[0].SemestreMateriaPensum;
                    foreach (Prelacion miPrelacionObligatoria in misPrelacionesObligatorias)
                    {
                        if (miPrelacionObligatoria.SemestreMateriaPensum == menorSemestre)
                        {
                            misMateriasObligatorias.Add(miPrelacionObligatoria.MiMateriaPensum);
                        }
                    }
                    return misMateriasObligatorias;
                }
                catch (Exception)
                {
                    return null;
                }
            }

            public List<SeccionMateria> GenerarSeccionesMateria(Materia miMateria)
            {
                //regresa la lista de secciones materias!!

                try
                {
                    SqlServerHorarioPreMatricula bdMateria = new SqlServerHorarioPreMatricula();
                    List<SeccionMateria> misSecciones = bdMateria.ConsultarSeccionesParaUnaMateria(miMateria.Codigo);
                    return misSecciones;
                }
                catch (Exception)
                {
                    return null;
                }
            }

            public bool ExistNombrePreMatricula(string miNombrePreMatricula)
            {
                //Verifica que el nombre asignado a una prematricula no sea repetido.

                try
                {
                    foreach (HorarioPreMatricula miHorarioPreMatricula in this._listaHorarioPreMatricula)
                    {
                        if (miHorarioPreMatricula.Nombre.Equals(miNombrePreMatricula))
                        {
                            return true;
                        } // poner un try catch para agarrar la exception de nulo
                    }
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            }

            public void LoadPreMatriculas()
            {
                //Muestra lpor pantalla las prematricula de un estudiante

                try
                {
                    SqlServerHorarioPreMatricula dbPreMatriculas = new SqlServerHorarioPreMatricula();
                    this.ListaHorarioPreMatricula = dbPreMatriculas.CargarMisHorarios(this._idEst);
                }
                catch (Exception)
                { }
            }

            public List<SeccionMateria> ListaPracticasMateria()
            {
                //Esta Funcion Revibe una lista de todas las practicas seleccionadas por el estudiante

                try
                {
                    List<SeccionMateria> retorno = new List<SeccionMateria>();
                    SqlServerHorarioPreMatricula sql = new SqlServerHorarioPreMatricula();
                    retorno = sql.ListaPracticas(_misSeccionesSeleccionadasPreMatricula);
                    return retorno;
                }
                catch (Exception)
                {
                    return null;
                }
            }
            
            public bool ExistPractica(int id, List<Practica> misPracticas)
            {
                //La funcion verifica si la practica posee o no alguna practica.
                //regresa true si tiene practica.

                try
                {
                    foreach (Practica miPractica in misPracticas)
                    {
                        if (miPractica.IdPractica == id)
                        {
                            return true;
                        }
                    }
                    return false;
                }
                catch (Exception)
                {
                    return false;
                }
            }

            public bool ValidarChoqueHorario(List<SeccionMateria> ListaMateriasSelec)
            {
                //Esta Funcion Se encarga de Validar que la lista de horarios seleccionada por el
                //estudiante no tenga conflicto entre los horarios, esta funcion recorre la lista seleccionada
                //para comparar todos los horarios y revisar si no hay choque de horarios, la funcion regresa un
                //true si no hay conflicto y un False si hay conflicto en horario.

                try
                {
                    bool bandera = true;

                    List<HorarioDeClase> listaDeHorarios = new List<HorarioDeClase>();

                    foreach (SeccionMateria miSeccion in ListaMateriasSelec)
                    {
                        foreach (HorarioDeClase miHorarioTeoria in miSeccion.HorasClase)
                        {
                            listaDeHorarios.Add(miHorarioTeoria);
                        }
                        if (miSeccion.ListaPractica.Count != 0)
                            foreach (HorarioDeClase miHorarioPractica in miSeccion.ListaPractica[0].horarioDeClase)
                            {
                                listaDeHorarios.Add(miHorarioPractica);
                            }
                    }

                    foreach (HorarioDeClase miHorario1 in listaDeHorarios)
                    {
                        int contador = 0;
                        foreach (HorarioDeClase miHorario2 in listaDeHorarios)
                        {
                            if (miHorario1.IdHorarioClase == miHorario2.IdHorarioClase)
                                contador++;
                            else
                            {
                                if (miHorario1.Dia == miHorario2.Dia)
                                {
                                    if (((miHorario1.HoraInicio.Hour < miHorario2.HoraInicio.Hour) &&
                                       (miHorario2.HoraInicio.Hour < miHorario1.HoraFin.Hour)) ||
                                       ((miHorario1.HoraInicio.Hour < miHorario2.HoraFin.Hour) &&
                                       (miHorario2.HoraFin.Hour < miHorario1.HoraFin.Hour)))
                                    {
                                        bandera = false;

                                        HorarioChoque1 = new HorarioDeClase();
                                        HorarioChoque1 = miHorario1;

                                        HorarioChoque2 = new HorarioDeClase();
                                        HorarioChoque2 = miHorario2;
                                    }
                                }
                            }
                            if (contador > 1)
                                bandera = false;
                        }
                    }

                    return bandera;
                }
                catch (Exception)
                {
                    return false;
                }
            }

            public void AsignarPreMatriculaModificable(int idPreMatricula)
            {
                foreach (HorarioPreMatricula miPreMatriculaModificable in this.ListaHorarioPreMatricula)
                {
                    if (miPreMatriculaModificable.Codigo == idPreMatricula)
                        PreMatriculaModificable = miPreMatriculaModificable;
                }
            }

            public int MaxCreditos()
            {                
                /*
                 * funcion que me retorna el numero maximo de creditos que puede ver un alumno en un semestre nuevo
                 */

                int retorno = 0;
                SqlServerHorarioPreMatricula sql = new SqlServerHorarioPreMatricula();
                List<Prelacion> materias = new List<Prelacion>();
                List<int> creditos = new List<int>();

                for (int contador1 = 0; contador1 < 10; contador1++)
                    creditos.Add(0);

                materias = sql.MateriasDisponibles(this._carrera);

                for (int contador = 1; contador < 11; contador++)
                {
                    foreach (Prelacion prelacion in materias)
                    {
                        if (prelacion.SemestreMateriaPensum == contador)
                            creditos[contador-1] = prelacion.CreditoMateriaPensum + creditos[contador-1];
                    }
                }

                foreach (int credito in creditos)
                {
                    if (credito > retorno)
                        retorno = credito;
                }

                return retorno;
            }

            public int CreditoMateria(int idMateria)
            {
                try
                {
                    int retorno = 0;

                    SqlServerHorarioPreMatricula sql = new SqlServerHorarioPreMatricula();
                    List<Prelacion> misPrelaciones = new List<Prelacion>();

                    misPrelaciones = sql.MateriasDisponibles(this._carrera);

                    foreach (Prelacion miPrelacion in misPrelaciones)
                    {
                        if (miPrelacion.MiMateriaPensum.Codigo == idMateria)
                            retorno = miPrelacion.CreditoMateriaPensum;
                    }

                    return retorno;
                }
                catch (Exception)
                {
                    return 0;
                }
            }

            protected string LoadHorarios(HorarioDeClase miHorario)
            {
                string miHorarioArmado;
                string minuteIni;
                string minuteFin;

                if (miHorario.HoraInicio.Minute.ToString().Length < 2)
                    minuteIni = "0" + miHorario.HoraInicio.Minute.ToString();
                else
                    minuteIni = miHorario.HoraInicio.Minute.ToString();

                if (miHorario.HoraFin.Minute.ToString().Length < 2)
                    minuteFin = "0" + miHorario.HoraFin.Minute.ToString();
                else
                    minuteFin = miHorario.HoraFin.Minute.ToString();
                miHorarioArmado = miHorario.Dia + ": " + miHorario.HoraInicio.Hour.ToString() + ":" +
                                minuteIni + " a " + miHorario.HoraFin.Hour.ToString() + ":" + minuteFin +
                                " en " + miHorario.SalonDeClase.Nombre + " .    ";
                return miHorarioArmado;
            }    

            public bool EnviarCorreo(int idEstudiante, int idHorario, string subject)
            {
                /*
                 * Este procedimiento se encarga de mandarle un correo al estudiante indicandole horario que
                 * modifico o registro
                 */

                this.LoadPreMatriculas();
                MailMessage correo = new MailMessage();
                HorarioPreMatricula miHorarioPreMatricula = new HorarioPreMatricula();

                correo.To.Add(new MailAddress("juanc.coellop@gmail.com"));
                correo.From = new MailAddress("vudu.mail.service@gmail.com");
                correo.Subject = subject;

                miHorarioPreMatricula = ListaHorarioPreMatricula[ListaHorarioPreMatricula.Count - 1];
                correo.Body = "Hemos registrado el horario identificado con el nombre: " + miHorarioPreMatricula.Nombre +
                        "\n\n\n";
                foreach (SeccionMateria misSecciones in miHorarioPreMatricula.ListaSecciones)
                {
                    correo.Body += misSecciones.Materia.Nombre + " " +
                                    misSecciones.Profesor.Nombre + " " + misSecciones.Profesor.Apellido + "\n\n";
                    misSecciones.HorasClase.Sort(delegate(HorarioDeClase miHorario1, HorarioDeClase miHorario2)
                    {
                        return miHorario1.Dia.CompareTo(miHorario2.Dia);
                    });
                    foreach (HorarioDeClase miHorario in misSecciones.HorasClase)
                    {
                        correo.Body += LoadHorarios(miHorario);
                    }
                    correo.Body += "\n\n\n";
                    if (misSecciones.ListaPractica != null)
                    {
                        foreach (Practica miPractica in misSecciones.ListaPractica)
                        {
                            correo.Body += miPractica.NombrePractica;
                            miPractica.horarioDeClase.Sort(delegate(HorarioDeClase miHorario1, HorarioDeClase miHorario2)
                            {
                                return miHorario1.Dia.CompareTo(miHorario2.Dia);
                            });
                            foreach (HorarioDeClase miHorario in miPractica.horarioDeClase)
                            {
                                correo.Body += LoadHorarios(miHorario);
                            }
                            correo.Body += "\n\n\n";
                        }
                    }
                }

                SmtpClient client = new SmtpClient("smtp.gmail.com", 587)
                {
                    Credentials = new NetworkCredential("vudu.mail.service@gmail.com", "vudu12345universidad"),
                    EnableSsl = true
                };

                try
                {

                    client.Send(correo);
                    return true;
                }

                catch (Exception)
                {
                    return false;
                }
            }

            public bool ExistPreMatriculaActiva()
            {
                this.LoadPreMatriculas();
                if(this.ListaHorarioPreMatricula != null)
                    foreach (HorarioPreMatricula miPrematricula in this.ListaHorarioPreMatricula)
                    {
                        if(miPrematricula.Estatus.Equals("Activo"))
                        {
                            return true;
                        }
                    }
                return false;
            }

        #endregion Fin de los Procedimientos y Funciones del GRUPO 2


        #region Grupo 6 metodos
            public int relacionEscuelaEstudiante(int _idUsuario)
            {
                SqlServerPensum sqlServerPensum = new SqlServerPensum();
                return sqlServerPensum.ConsultarEscuelaEstudiante(_idUsuario);
            }
        #endregion

        #endregion
    }
}